Kolejne crackme z czaswWin 98. I znw mysl, e wasnie dlatewgo tak dugo zostao nierozwizane. bo tak naprawde nie ma w nim nic trudnego. Chyba e jest tak proste e nikomu nie chciao si go rozwizywa. Ale do rzeczy. Crackme jest consolowe, a dodatkowo w charakterystyce ma ustawione, e jest bibliotek dll. I rzeczywicie eksportuje funkcj, ale o tym pniej. Napisane jest w Delphi, wic sporo calli jest do funkcji typowych dla Delphi, ktrych nie omawiam, bo sam wikszoci nie znam ;-). Po kolei.

  public start
CODE:00406C78 start           proc near
CODE:00406C78                 push    ebp
CODE:00406C79                 mov     ebp, esp
CODE:00406C7B                 add     esp, 0FFFFFFF4h
CODE:00406C7E                 call    @System@@InitDll$qqrv ; System::__linkproc__ InitDll(void)
CODE:00406C83                 jnz     _HALT0

Poniewa plik jest biblioteka musi by widocznie uruchomiony w sposb wasciwy dla Dll-ek.
Waniejszy jest poniejszy element.

                
CODE:00406756                 mov     eax, offset please_wait.Text
CODE:0040675B                 call    sub_40636C
CODE:00406760                 mov     edx, [ebp+var_230]
CODE:00406766                 mov     eax, offset unk_408200
CODE:0040676B                 call    sub_403534
CODE:00406770                 call    sub_403C68
CODE:00406775                 lea     ecx, [ebp+var_230]
CODE:0040677B                 mov     edx, 0FFFFFFB2h
CODE:00406780                 mov     eax, offset _str_______0.Text
CODE:00406785                 call    sub_40636C      ; zamiana stringa
CODE:0040678A                 mov     eax, [ebp+var_230]
CODE:00406790                 call    @System@@LStrToPChar$qqrv ; System::__linkproc__ LStrToPChar(void)
CODE:00406795                 push    eax             ; lpName                        <----------------nazwa pliku (pt887)
CODE:00406796                 push    100h            ; dwMaximumSizeLow
CODE:0040679B                 push    0               ; dwMaximumSizeHigh
CODE:0040679D                 push    4               ; flProtect
CODE:0040679F                 push    0               ; lpFileMappingAttributes
CODE:004067A1                 push    0FFFFFFFFh      ; hFile
CODE:004067A3                 call    CreateFileMappingA        <---------------------tworzy plik odwzorowany w pamici
CODE:004067A8                 mov     [ebp+hFileMappingObject], eax
CODE:004067AB                 push    0               ; dwNumberOfBytesToMap
CODE:004067AD                 push    0               ; dwFileOffsetLow
CODE:004067AF                 push    0               ; dwFileOffsetHigh
CODE:004067B1                 push    2               ; dwDesiredAccess
CODE:004067B3                 mov     eax, [ebp+hFileMappingObject]
CODE:004067B6                 push    eax             ; hFileMappingObject
CODE:004067B7                 call    MapViewOfFile                      <------------------odwzorowuje plik w pamieci
CODE:004067BC                 mov     [ebp+var_18], eax
CODE:004067BF                 mov     eax, [ebp+var_18]
CODE:004067C2                 mov     dword ptr [eax+200h], 82h
CODE:004067CC                 mov     word ptr [eax+204h], 0
CODE:004067D5                 lea     ecx, [ebp+var_230]
CODE:004067DB                 mov     edx, 8
CODE:004067E0                 mov     eax, offset rundll32.Text     <---------------------element stringa
CODE:004067E5                 call    sub_40636C
CODE:004067EA                 push    [ebp+var_230]
CODE:004067F0                 lea     edx, [ebp+var_238]
CODE:004067F6                 xor     eax, eax
CODE:004067F8                 call    @System@ParamStr$qqri ; System::ParamStr(int)
CODE:004067FD                 mov     eax, [ebp+var_238]
CODE:00406803                 lea     edx, [ebp+var_234]
CODE:00406809                 call    sub_404B74
CODE:0040680E                 push    [ebp+var_234]
CODE:00406814                 push    offset _str__c1_.Text   <---------------------element stringa
CODE:00406819                 lea     eax, [ebp+var_4]
CODE:0040681C                 mov     edx, 3
CODE:00406821                 call    @System@@LStrCatN$qqrv ; System::__linkproc__ LStrCatN(void) 
CODE:00406826                 push    1               ; uCmdShow
CODE:00406828                 mov     eax, [ebp+var_4]
CODE:0040682B                 call    @System@@LStrToPChar$qqrv ; System::__linkproc__ LStrToPChar(void)
CODE:00406830                 push    eax             ; lpCmdLine
CODE:00406831                 call    WinExec

Wszystkie ancuchy teksotwe uywane w crackme s szyfrowane, ale w bardzo prosty sposb, wic omwie go tylko oglnie. Do funkcji podawany jest zaszyfowany ancuch i liczba odszyfrowujca. Sposb odszyfrowania jest prosty jest to naczciej prosty add lub sub.
W powyszym fragmencie kodu. Tworzony jest plik odwzorowany w pamici o nazwie pt778. Gwn zalet takiego pliku jest mozliwo uzywania go przez kilka procesw i w ten sposb wymiana danych midzy nimi, co wanie tutaj zostanie zastosowane.
Nastepnie z zaszyfrowanych acuchw twrzony jest nastepujcy acuch :"rundll32 Crackme2,c1 " i program rundll32.exe uruchamiany jest funkcjWinexec. Oznacza to, e w naszym crackme zostaje uruchomiona eksportowana funkcja o nazwie c1. W ten sposb mamy uruchomione juz dwa procesy.
Najpierw omwimy co robi podstawowy proces.

                 lea     ecx, [ebp+var_230]
CODE:004068A4                 mov     edx, 36h
CODE:004068A9                 mov     eax, offset user.Text                                 <--------------string "User:"
CODE:004068AE                 call    sub_40636C
CODE:004068B3                 mov     edx, [ebp+var_230]
CODE:004068B9                 mov     eax, offset unk_408200
CODE:004068BE                 call    sub_403534
CODE:004068C3                 call    sub_403C68
CODE:004068C8                 lea     edx, [ebp+var_22C]
CODE:004068CE                 mov     ecx, 0FFh
CODE:004068D3                 mov     eax, offset unk_408034
CODE:004068D8                 call    _READSTRING			<-------- no comments
CODE:004068DD                 mov     eax, offset unk_408034
CODE:004068E2                 call    _READLN 			
CODE:004068E7                 lea     eax, [ebp+var_8]
CODE:004068EA                 lea     edx, [ebp+var_22C]
CODE:004068F0                 call    @System@@LStrFromString$qqrv ; System::__linkproc__ LStrFromString(void)
CODE:004068F5                 mov     eax, [ebp+var_8]
CODE:004068F8                 call    @System@_16823  ; System::_16823
CODE:004068FD                 test    al, al
CODE:004068FF                 jbe     short loc_406931
CODE:00406901                 mov     [ebp+var_25], al
CODE:00406904                 mov     [ebp+var_D], 1
CODE:00406908
CODE:00406908 loc_406908:                             ; CODE XREF: sub_406714+21Bj
CODE:00406908                 lea     eax, [ebp+var_8]
CODE:0040690B                 call    @System@UniqueString$qqrr17System@AnsiString ; System::UniqueString(System::AnsiString &)
CODE:00406910                 xor     edx, edx
CODE:00406912                 mov     dl, [ebp+var_D]
CODE:00406915                 xor     ecx, ecx
CODE:00406917                 mov     cl, [ebp+var_D]
CODE:0040691A                 mov     ebx, [ebp+var_8]
CODE:0040691D                 movzx   ecx, byte ptr [ebx+ecx-1]         <--------wczytanie znaku
CODE:00406922                 add     ecx, 37h                 <-------------------zaszyfrowanie ;-)           
CODE:00406925                 mov     [eax+edx-1], cl      <----------------------zapisanie zaszyfrowanego
CODE:00406929                 inc     [ebp+var_D]
CODE:0040692C                 dec     [ebp+var_25]
CODE:0040692F                 jnz     short loc_406908

Najpierw jestesmy pytani o nazwe usera, poniej dane wprowadzone zamienione s na string ,a ten zaszyfrowany za pomoc dodania 37h do orginalnego znaku.

CODE:0040693C                 mov     eax, offset serial.Text       <------------------string "Serial:"
CODE:00406941                 call    sub_40636C
CODE:00406946                 mov     edx, [ebp+var_230]
CODE:0040694C                 mov     eax, offset unk_408200
CODE:00406951                 call    sub_403534
CODE:00406956                 call    sub_403C68
CODE:0040695B                 lea     edx, [ebp+var_12C]
CODE:00406961                 mov     ecx, 0FFh
CODE:00406966                 mov     eax, offset unk_408034
CODE:0040696B                 call    _READSTRING
CODE:00406970                 mov     eax, offset unk_408034
CODE:00406975                 call    _READLN
CODE:0040697A                 lea     eax, [ebp+var_C]
CODE:0040697D                 lea     edx, [ebp+var_12C]
CODE:00406983                 call    @System@@LStrFromString$qqrv ; System::__linkproc__ LStrFromString(void)
CODE:00406988                 mov     eax, [ebp+var_C]
CODE:0040698B                 call    @System@_16823  ; System::_16823
CODE:00406990                 cmp     eax, 3
CODE:00406993                 jl      short loc_4069A2                                    <----------------jesli iloc mniejsza od 3, to ExitProcess
CODE:00406995                 mov     eax, [ebp+var_8]
CODE:00406998                 call    @System@_16823  ; System::_16823
CODE:0040699D                 cmp     eax, 3
CODE:004069A0                 jge     short loc_4069B6
CODE:004069A2
CODE:004069A2 loc_4069A2:                             ; CODE XREF: sub_406714+27Fj
CODE:004069A2                 mov     eax, [ebp+var_18]
CODE:004069A5                 mov     esi, offset aTt ; "tt"
CODE:004069AA                 mov     edi, eax
CODE:004069AC                 movsw
CODE:004069AE                 movsb
CODE:004069AF                 push    0
CODE:004069B1                 call    ExitProcess_0
CODE:004069B6
CODE:004069B6 loc_4069B6:                             ; CODE XREF: sub_406714+28Cj
CODE:004069B6                 mov     eax, [ebp+var_C]
CODE:004069B9                 call    @System@_16823  ; System::_16823
CODE:004069BE                 test    al, al
CODE:004069C0                 jbe     short loc_4069F2
CODE:004069C2                 mov     [ebp+var_25], al
CODE:004069C5                 mov     [ebp+var_D], 1
CODE:004069C9
CODE:004069C9 loc_4069C9:                             ; CODE XREF: sub_406714+2DCj
CODE:004069C9                 lea     eax, [ebp+var_C]
CODE:004069CC                 call    @System@UniqueString$qqrr17System@AnsiString ; System::UniqueString(System::AnsiString &)
CODE:004069D1                 xor     edx, edx
CODE:004069D3                 mov     dl, [ebp+var_D]
CODE:004069D6                 xor     ecx, ecx
CODE:004069D8                 mov     cl, [ebp+var_D]
CODE:004069DB                 mov     ebx, [ebp+var_C]
CODE:004069DE                 movzx   ecx, byte ptr [ebx+ecx-1]
CODE:004069E3                 sub     ecx, 10h                                      <----------------------------szyfrowanie seriala
CODE:004069E6                 mov     [eax+edx-1], cl
CODE:004069EA                 inc     [ebp+var_D]
CODE:004069ED                 dec     [ebp+var_25]
CODE:004069F0                 jnz     short loc_4069C9

Teraz proszeni jestesmy o serial duszy ni 3 znaki, bo inaczej exit. Serial zostaje zaszyfowany przez odjcie od orginalnego znaku 10h.
Zarwno zaszyfrowany name jak i serial zostaj zapisane do pliku odwzorowanego w pamieci. Teraz nadchodzi czas na dziaanie drugiego procesu, czyli funkcji c1.

CODE:00406445                 push    eax             ; lpName                                <--------------- ta sama nazwa pliku
CODE:00406446                 push    100h            ; dwMaximumSizeLow
CODE:0040644B                 push    0               ; dwMaximumSizeHigh
CODE:0040644D                 push    4               ; flProtect
CODE:0040644F                 push    0               ; lpFileMappingAttributes
CODE:00406451                 push    0FFFFFFFFh      ; hFile
CODE:00406453                 call    CreateFileMappingA
CODE:00406458                 mov     [ebp+hFileMappingObject], eax
CODE:0040645B                 push    0               ; dwNumberOfBytesToMap
CODE:0040645D                 push    0               ; dwFileOffsetLow
CODE:0040645F                 push    0               ; dwFileOffsetHigh
CODE:00406461                 push    2               ; dwDesiredAccess
CODE:00406463                 mov     eax, [ebp+hFileMappingObject]
CODE:00406466                 push    eax             ; hFileMappingObject
CODE:00406467                 call    MapViewOfFile
CODE:0040646C                 mov     [ebp+var_8], eax
CODE:0040646F                 mov     eax, [ebp+var_8]
CODE:00406472                 mov     esi, eax

Funkcja c1 take tworzy plik odwzorowany w pamici. Poniewa jednak podaj t sam nazw co poprzedni proces, to uzyskuje dotp do tego samego pliku.

CODE:004064AD                 push    8               ; dwMilliseconds
CODE:004064AF                 call    Sleep				<--------------czekaj
CODE:004064B4                 mov     eax, [ebp+var_8]
CODE:004064B7                 mov     edx, offset unk_4065EC
CODE:004064BC                 xor     ecx, ecx
CODE:004064BE                 mov     cl, [eax]
CODE:004064C0                 inc     ecx
CODE:004064C1                 call    @System@@AStrCmp$qqrv ; System::__linkproc__ AStrCmp(void)
CODE:004064C6                 jz      short loc_4064AD

Nastepnie proces sprawdza czy poprzedni proces skoczy ju swoje zadanie, czyli czy pobra dane i zaszyfrowal je. Jeli nie proces czeka, jesli tak przechodzi do swojej roli.

CODE:00406501                 xor     eax, eax
CODE:00406503                 mov     al, [ebp+var_E]
CODE:00406506                 mov     edx, [ebp+var_C]
CODE:00406509                 mov     al, [edx+eax-1]     <----------------wczytaj zaszyfrowany znak
CODE:0040650D                 mov     edx, eax
CODE:0040650F                 shl     eax, 3                     <-------------------pomn razy 8
CODE:00406512                 sub     eax, edx 	            <--------------------odejmij przemnozony znak od  zaszyfrowanego
CODE:00406514                 add     [ebp+var_D], al    <------------------zsumuj i przechowaj
CODE:00406517                 inc     [ebp+var_E]
CODE:0040651A                 dec     [ebp+var_10]
CODE:0040651D                 jnz     short loc_406501

Zaszyfrowany name poddany zostaje prostym dziaaniom a suma poszczeglnych znakw przechowywana jest w zmiennej.

CODE:00406544                 xor     eax, eax
CODE:00406546                 mov     al, [ebp+var_E]
CODE:00406549                 mov     edx, [ebp+var_C]
CODE:0040654C                 mov     al, [edx+eax-1]
CODE:00406550                 lea     eax, [eax+eax*2]  <------------------------przemnz razy 3
CODE:00406553                 add     [ebp+var_F], al     <-----------------------zsumuj i przechowaj
CODE:00406556                 inc     [ebp+var_E]
CODE:00406559                 dec     [ebp+var_10]
CODE:0040655C                 jnz     short loc_406544

Podobnie jest z serialem . kazdy znak zostaje przemnoony przez trzy i zsumowany.

CODE:0040655E                 mov     al, [ebp+var_D]  
CODE:00406561                 cmp     al, [ebp+var_F]     <------------porwnanie obu zmiennych
CODE:00406564                 jnz     short loc_40657A
CODE:00406566                 mov     eax, [ebp+var_8]
CODE:00406569                 xor     edx, edx                          <-----------wyzeruj edx
CODE:0040656B                 mov     [eax+200h], edx           <--------------zapisz w odpowiednie miejsce w pamici
CODE:00406571                 mov     [eax+204h], dx
CODE:00406578                 jmp     short loc_40659B         <----------------zakocz dziaanie

nastepnie wyniki obu operacji zostaj porwnane. Jeli s rwne w odpowiednie miejsce w pamieci zapisane zostaj zera. Jeli nie w to miejsce zapisane s wartoci niezerowe. Po tym proces koczy dziaanie.

Wrcmy do pierwszego procesu.
CODE:00406A19                 call    Sleep			<------------------zawieszenie dziaania na chwil
CODE:00406A1E                 mov     [ebp+var_1E], 87h
CODE:00406A25                 mov     [ebp+var_1A], 7600h
CODE:00406A2B                 mov     eax, [ebp+var_18]
CODE:00406A2E                 mov     edx, [eax+200h]               <----------------pobranie danych zapisanych przez 2 proces
CODE:00406A34                 mov     [ebp+var_1E], edx
CODE:00406A37                 mov     dx, [eax+204h]	        <----------------pobranie danych zapisanych przez 2 proces
CODE:00406A3E                 mov     [ebp+var_1A], dx
CODE:00406A42                 xor     eax, eax
CODE:00406A44                 push    ebp
CODE:00406A45                 push    offset loc_406A9A		<------------ustawienie obsugi wyjatkw
CODE:00406A4A                 push    dword ptr fs:[eax]
CODE:00406A4D                 mov     fs:[eax], esp
CODE:00406A50                 lea     eax, [ebp+var_1E]
CODE:00406A53                 call    unknown_libname_14 ; Delphi 5 Visual Component Library
CODE:00406A58                 fdivr   ds:dword_406C1C                            <---------------------- dzielenie
CODE:00406A5E                 lea     eax, [ebp+var_24]
CODE:00406A61                 call    _EXT2REAL

Pierwszy proces zawiesi dzialanie, eby drugi mg wykona swoje obliczenia. Po czym pobiera wyniki oblicze, ustawia obsuge wyjtku, i dokonuje dzielenia.
Rozwizanie nasuwa si samo. Jesli drugi proces wpisze zera, ktre pobierze pierwszy proces i podzieli przez nie liczb, nastpi wyjatek ktry zostanie obsuony.
A co wykona si w obsludze wyjatku ??

CODE:00406A9F                 dd 1
CODE:00406AA3                 dd offset aEzerodivide  ; "EZeroDivide"   <---------------- jesli wyjatek to dzielenie przez zero
CODE:00406AA7                 dd offset loc_406AAB
CODE:00406AAB ; 
CODE:00406AAB
CODE:00406AAB loc_406AAB:                             ; DATA XREF: sub_406714+393o
CODE:00406AAB                 lea     ecx, [ebp-230h]
CODE:00406AB1                 mov     edx, 0FFFFFFB3h
CODE:00406AB6                 mov     eax, offset serial_prawidlowy        <---------------zaszyforwany Good Boy
CODE:00406ABB                 call    sub_40636C		<---------------odszyfrowanie
CODE:00406AC0                 lea     eax, [ebp-230h]
CODE:00406AC6                 mov     edx, offset _str___.Text    
CODE:00406ACB                 call    @System@@LStrCat$qqrv ; System::__linkpr   <----- poaczenie stringw

W obsudze wyjtku zostajemy skierowani do komunikatu Good Boy. I to ju cale rozwizanie.
Keygena nie pisze, gdy nie dla wszystkich userw mozliwe jest wygenerowanie seriala. Podam je jednak na jednym przykadzie, dla uatwienia.

user:"asasm"
Zostaje zaszyfrowane przez add 37h, a potem shl,3 i sub a nastpnie zsumowane add. Kocowy wynik to 018h.
Teraz jak wygenerowa serial ?? Po pierwsze wynik musi by podzielny przez 3 i do duy .
018h/3=4 ,ale to nam nic nie daje. Poniewa jednak wynik zosta obciety tylko do 8 bitw (al), zamiast 18h moe byc 118h lub 218h,318h; byleby byy podzielne przez 3, poniwa kady znak zaszyfrowanego seriala by mnozony przez 3.
318h/3=108h, <- tyle wynosi suma zaszyfrowanego seriala.
teraz 108h/8=21h <--- czyli przykladowy zaszyfrowany serial to 8 znakw 21h.
Poniwa szyfrowanie to odjecie 10h od kadego znaku, to odszyfrowany serial to np. 8 znakw 31h,
czyli "11111111"
podobn sum da rwnie "20202020", "888(888","P88888","@@X@@" itd.

Wic przykladowa para to:
user:asasm
serial:11111111

I to by byo na tyle.......
